﻿#include "../exercise.h"
#include <numeric>

// READ: `std::accumulate` <https://zh.cppreference.com/w/cpp/algorithm/accumulate>

int main(int argc, char **argv) {
    using DataType = float;
    int shape[]{1, 3, 224, 224};
    // TODO: 调用 `std::accumulate` 计算：
    //       - 数据类型为 float；
    //       - 形状为 shape；
    //       - 连续存储；
    //       的张量占用的字节数
    // int size = ?;

    // 计算元素总数：1 * 3 * 224 * 224
    int element_count = std::accumulate(
        std::begin(shape), std::end(shape), 1, std::multiplies<int>()
    );

    // 计算总字节数：元素总数 × 每个元素的大小
    int size = element_count * sizeof(DataType);

    ASSERT(size == 602112, "4x1x3x224x224 = 602112");
    return 0;
}


/*
`std::accumulate`


方法思路
理解张量形状：shape[]{1, 3, 224, 224} 表示4维张量
计算元素总数：所有维度的乘积
计算字节数：元素总数 × 每个元素的大小（sizeof(DataType)）





代码解释
1. 计算元素总数
int element_count = std::accumulate(
    std::begin(shape), std::end(shape), 1, std::multiplies<int>()
);
参数说明：

std::begin(shape), std::end(shape)：要累乘的范围
1：初始值（乘法运算的初始值应为1）
std::multiplies<int>()：二元操作函数对象，执行乘法运算
2. 计算字节数
int size = element_count * sizeof(DataType);
element_count：元素总数（1 × 3 × 224 × 224 = 150528）
sizeof(DataType)：每个元素的大小（sizeof(float) = 4字节）
总字节数：150528 × 4 = 602112
验证计算
让我们手动验证一下：

维度: 1 × 3 × 224 × 224 = 150528 个元素
每个float元素: 4 字节
总字节数: 150528 × 4 = 602112 字节
替代实现方式
1. 使用lambda表达式
int element_count = std::accumulate(
    std::begin(shape), std::end(shape), 1,
    [](int a, int b) { return a * b; }
);
2. 手动循环计算
int element_count = 1;
for (int i = 0; i < 4; ++i) {
    element_count *= shape[i];
}
int size = element_count * sizeof(DataType);
3. 直接计算（硬编码）
int size = 1 * 3 * 224 * 224 * sizeof(float);
std::accumulate 的更多用法
1. 求和（默认行为）
std::vector<int> numbers{1, 2, 3, 4, 5};
int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
// sum = 15
2. 字符串连接
std::vector<std::string> words{"Hello", " ", "World", "!"};
std::string sentence = std::accumulate(words.begin(), words.end(), std::string());
// sentence = "Hello World!"
3. 自定义操作
// 求最大值（需要包含 <algorithm> 和 <functional>）
std::vector<int> numbers{3, 1, 4, 1, 5};
int max_val = std::accumulate(numbers.begin(), numbers.end(), 0,
    [](int a, int b) { return std::max(a, b); });
// max_val = 5
实际应用场景
1. 计算多维数组大小
// 计算3D数组的总大小
int dimensions[]{10, 20, 30};
int total_elements = std::accumulate(
    std::begin(dimensions), std::end(dimensions), 1, std::multiplies<int>()
);
2. 计算乘积
// 计算阶乘
std::vector<int> factors{1, 2, 3, 4, 5};
int factorial = std::accumulate(
    factors.begin(), factors.end(), 1, std::multiplies<int>()
);
// factorial = 120
3. 统计计算
// 计算加权平均值
std::vector<std::pair<double, double>> data{{1.0, 0.1}, {2.0, 0.2}, {3.0, 0.3}};
double weighted_avg = std::accumulate(data.begin(), data.end(), 0.0,
    [](double sum, const auto& pair) { return sum + pair.first * pair.second; });
性能考虑
std::accumulate 是线性时间复杂度 O(n)
对于小数组，性能很好
对于非常大的数组，可以考虑并行算法（如 std::reduce in C++17）
测试验证
程序运行后会通过测试：

计算出的字节数等于 602112
验证了张量形状 [1, 3, 224, 224] 和 float 数据类型的正确计算
这个练习展示了 std::accumulate 的强大功能，特别是如何使用自定义操作函数（如 std::multiplies）来进行乘法累加运算。
*/
